layui.define(['jquery', 'form', 'layer', 'table', 'laydate', 'upload', 'element', 'laytpl', 'tableSelect'], function (exports) {
    "use strict";

    let $ = layui.jquery
        , form = layui.form
        , layer = layui.layer
        , table = layui.table
        , laydate = layui.laydate
        , upload = layui.upload
        , element = layui.element
        , laytpl = layui.laytpl
        , tableSelect = layui.tableSelect;

    /**
     * 控制输入区域只能输入数字 (需要同时为标签的onkeyup添加此方法，并将自身传入)
     * eg:onkeyup="javascript:onlyNumber(this)"
     * @param obj
     */
    window.onlyNumber = function (obj) {
        let val = obj.value;
        if (val == '-') {
            return;
        }
        if (isNaN(val)) {
            obj.value = "";
            obj.focus();
        }
    }

    /**
     * 控制输入区域只能输入正整数 (需要同时为标签的onkeyup添加此方法，并将自身传入)
     * eg:onkeyup="javascript:onlyInteger(this)"
     * @param obj
     */
    window.onlyInteger = function (obj) {
        let val = obj.value;
        if (!/^\d+$/.exec(val)) {
            obj.value = "";
            obj.focus();
        }
    }

    /**
     * 手机号码验证
     * @param phoneNumber
     * @returns {boolean}
     */
    window.validatePhoneNumber = function (phoneNumber) {
        // 手机号码必须全部由数字组成
        if (!/^1\d{10}$/.test(phoneNumber)) {
            return false;
        }
        return true;
    }

    /**
     * 删除上传的文件或图片
     * @param dom
     */
    window.removeUploadItem = function (dom) {
        $(dom).closest('.item').remove();
    }

    /**
     * 身份证号码验证
     * @param idCard 身份证号码
     * @returns {boolean}
     */
    window.validateIDCard = function (idCard) {
        // 身份证号码长度必须为18位
        if (idCard.length !== 18) {
            return false;
        }

        // 前17位必须是数字，第18位可以是数字或字母X（不区分大小写）
        if (!/^\d{17}[\dXx]$/.test(idCard)) {
            return false;
        }

        // 校验出生日期
        const year = idCard.substring(6, 10);
        const month = idCard.substring(10, 12);
        const day = idCard.substring(12, 14);

        const date = new Date(year, month - 1, day);
        if (date.getFullYear() !== parseInt(year) || date.getMonth() + 1 !== parseInt(month) || date.getDate() !== parseInt(day)) {
            return false;
        }

        // 校验码校验
        const weightFactors = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
        const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];

        let sum = 0;
        for (let i = 0; i < 17; i++) {
            sum += parseInt(idCard.charAt(i)) * weightFactors[i];
        }

        const checkCode = checkCodes[sum % 11];
        if (checkCode.toUpperCase() !== idCard.charAt(17).toUpperCase()) {
            return false;
        }

        return true;
    }

    /**
     * 导出通用的Word
     * @param fileName  导出文件的名称，无扩展名
     * @param dom  导出Word的内容元素，默认为当前文档的'#divPrint'元素，没有则是整个body
     * @param url  服务器响应的地址，可由COMMON_EXPORT_WORD_URL提前设定
     */
    window.exportWord = function (fileName, dom, url) {
        if (dom == null) {
            dom = '#divPrint';
            if ($(dom).size() == 0) {
                dom = 'body';
            }
        }
        if (url == null) {
            if (typeof COMMON_EXPORT_WORD_URL === 'string') {
                url = COMMON_EXPORT_WORD_URL;
            } else {
                url = '/' + CONFIG.MODULE + '/exportWord';
            }
        }
        let form = $('<form></form>').attr('action', url).attr('method', 'post');
        if (fileName != null) {
            form.append($('<input></input>').attr('type', 'hidden').attr('name', 'fileName').attr('value', fileName));
        }
        form.append($('<input></input>').attr('type', 'hidden').attr('name', 'content').attr('value', $(dom).html()));
        form.appendTo('body').submit().remove();
    }

    /**
     * 导出Excel
     * @param url
     */
    window.exportExcel = function (url) {
        let params = {};
        $('input,select').each(function () {
            let $this = $(this);
            if ($this.attr('name') == null) {
                return true;
            }
            if ($this.is(':radio')) {
            } else if ($this.is(':checkbox')) {
            } else if ($this.val() != '') {
                params[$this.attr('name')] = $this.val();
            }
        });
        location = '/' + CONFIG.MODULE + url + $.param(params, true);
    }

    /*Date 扩展方法*/
    if (typeof (Date.parseDate) == 'undefined') {
        if (typeof (Date._DN) == 'undefined') {
            // 星期名称
            Date._DN = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'];
            // 星期缩写名称
            Date._SDN = ['日', '一', '二', '三', '四', '五', '六', '日'];
            // 月份名称
            Date._MN = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'];
            // 月份缩写名称
            Date._SMN = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'];
        }
        /** Adds the number of days array to the Date object. */
        Date._MD = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

        /** Constants used for time computations */
        Date.SECOND = 1000 /* milliseconds */;
        Date.MINUTE = 60 * Date.SECOND;
        Date.HOUR = 60 * Date.MINUTE;
        Date.DAY = 24 * Date.HOUR;
        Date.WEEK = 7 * Date.DAY;

        Date.parseDate = function (str, fmt) {
            let today = new Date();
            let y = 0;
            let m = -1;
            let d = 0;
            let a = str.split(/\W+/);
            let b = fmt.match(/%./g);
            let i = 0, j = 0;
            let hr = 0;
            let min = 0;
            for (i = 0; i < a.length; ++i) {
                if (!a[i])
                    continue;
                switch (b[i]) {
                    case "%d":
                    case "%e":
                        d = parseInt(a[i], 10);
                        break;
                    case "%m":
                        m = parseInt(a[i], 10) - 1;
                        break;
                    case "%Y":
                    case "%y":
                        y = parseInt(a[i], 10);
                        (y < 100) && (y += (y > 29) ? 1900 : 2000);
                        break;
                    case "%b":
                    case "%B":
                        for (j = 0; j < 12; ++j) {
                            if (Date._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) {
                                m = j;
                                break;
                            }
                        }
                        break;
                    case "%H":
                    case "%I":
                    case "%k":
                    case "%l":
                        hr = parseInt(a[i], 10);
                        break;
                    case "%P":
                    case "%p":
                        if (/pm/i.test(a[i]) && hr < 12)
                            hr += 12;
                        else if (/am/i.test(a[i]) && hr >= 12)
                            hr -= 12;
                        break;
                    case "%M":
                        min = parseInt(a[i], 10);
                        break;
                }
            }
            if (isNaN(y)) y = today.getFullYear();
            if (isNaN(m)) m = today.getMonth();
            if (isNaN(d)) d = today.getDate();
            if (isNaN(hr)) hr = today.getHours();
            if (isNaN(min)) min = today.getMinutes();
            if (y != 0 && m != -1 && d != 0)
                return new Date(y, m, d, hr, min, 0);
            y = 0;
            m = -1;
            d = 0;
            for (i = 0; i < a.length; ++i) {
                if (a[i].search(/[a-zA-Z]+/) != -1) {
                    let t = -1;
                    for (j = 0; j < 12; ++j) {
                        if (Date._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) {
                            t = j;
                            break;
                        }
                    }
                    if (t != -1) {
                        if (m != -1) {
                            d = m + 1;
                        }
                        m = t;
                    }
                } else if (parseInt(a[i], 10) <= 12 && m == -1) {
                    m = a[i] - 1;
                } else if (parseInt(a[i], 10) > 31 && y == 0) {
                    y = parseInt(a[i], 10);
                    (y < 100) && (y += (y > 29) ? 1900 : 2000);
                } else if (d == 0) {
                    d = a[i];
                }
            }
            if (y == 0)
                y = today.getFullYear();
            if (m != -1 && d != 0)
                return new Date(y, m, d, hr, min, 0);
            return today;
        };

        /** Returns the number of days in the current month */
        Date.prototype.getMonthDays = function (month) {
            let year = this.getFullYear();
            if (typeof month == "undefined") {
                month = this.getMonth();
            }
            if (((0 == (year % 4)) && ((0 != (year % 100)) || (0 == (year % 400)))) && month == 1) {
                return 29;
            } else {
                return Date._MD[month];
            }
        };

        /** Returns the number of day in the year. */
        Date.prototype.getDayOfYear = function () {
            let now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
            let then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
            let time = now - then;
            return Math.floor(time / Date.DAY);
        };

        /** Returns the number of the week in year, as defined in ISO 8601. */
        Date.prototype.getWeekNumber = function () {
            let d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
            let DoW = d.getDay();
            d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
            let ms = d.valueOf(); // GMT
            d.setMonth(0);
            d.setDate(4); // Thu in Week 1
            return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
        };

        /** Checks date and time equality */
        Date.prototype.equalsTo = function (date) {
            return ((this.getFullYear() == date.getFullYear()) &&
                (this.getMonth() == date.getMonth()) &&
                (this.getDate() == date.getDate()) &&
                (this.getHours() == date.getHours()) &&
                (this.getMinutes() == date.getMinutes()));
        };

        /** Set only the year, month, date parts (keep existing time) */
        Date.prototype.setDateOnly = function (date) {
            let tmp = new Date(date);
            this.setDate(1);
            this.setFullYear(tmp.getFullYear());
            this.setMonth(tmp.getMonth());
            this.setDate(tmp.getDate());
        };

        /** Prints the date in a string according to the given format. */
        Date.prototype.print = function (str) {
            let m = this.getMonth();
            let d = this.getDate();
            let y = this.getFullYear();
            let wn = this.getWeekNumber();
            let w = this.getDay();
            let s = {};
            let hr = this.getHours();
            let pm = (hr >= 12);
            let ir = (pm) ? (hr - 12) : hr;
            let dy = this.getDayOfYear();
            if (ir == 0)
                ir = 12;
            let min = this.getMinutes();
            let sec = this.getSeconds();
            s["%a"] = Date._SDN[w]; // abbreviated weekday name [I18N]
            s["%A"] = Date._DN[w]; // full weekday name
            s["%b"] = Date._SMN[m]; // abbreviated month name [I18N]
            s["%B"] = Date._MN[m]; // full month name
            // %c : preferred date and time representation for the current locale
            s["%C"] = 1 + Math.floor(y / 100); // the century number
            s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
            s["%e"] = d; // the day of the month (range 1 to 31)
            // %D : american date style: %m/%d/%y
            // %E, %F, %G, %g, %h (man strftime)
            s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
            s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
            s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
            s["%k"] = hr;		// hour, range 0 to 23 (24h format)
            s["%l"] = ir;		// hour, range 1 to 12 (12h format)
            s["%m"] = (m < 9) ? ("0" + (1 + m)) : (1 + m); // month, range 01 to 12
            s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
            s["%n"] = "\n";		// a newline character
            s["%p"] = pm ? "PM" : "AM";
            s["%P"] = pm ? "pm" : "am";
            // %r : the time in am/pm notation %I:%M:%S %p
            // %R : the time in 24-hour notation %H:%M
            s["%s"] = Math.floor(this.getTime() / 1000);
            s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
            s["%t"] = "\t";		// a tab character
            // %T : the time in 24-hour notation (%H:%M:%S)
            s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
            s["%u"] = w + 1;	// the day of the week (range 1 to 7, 1 = MON)
            s["%w"] = w;		// the day of the week (range 0 to 6, 0 = SUN)
            // %x : preferred date representation for the current locale without the time
            // %X : preferred time representation for the current locale without the date
            s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
            s["%Y"] = y;		// year with the century
            s["%%"] = "%";		// a literal '%' character

            let re = /%./g;
            return str.replace(re, function (par) {
                return s[par] || par;
            });
        };

        Date.getFirstDayInMonth = function (year, month) {
            return new Date(year, month - 1, 1).print('%Y-%m-%d');
        }

        Date.getLastDayInMonth = function (year, month) {
            return new Date(year, month, 0).print('%Y-%m-%d');
        }

        Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear;
        Date.prototype.setFullYear = function (y) {
            let d = new Date(this);
            d.__msh_oldSetFullYear(y);
            if (d.getMonth() != this.getMonth())
                this.setDate(28);
            this.__msh_oldSetFullYear(y);
        };
    }

    let init = {
        table_elem: '#currentTable'
        , table_render_id: 'currentTable'
        , upload_url: 'ajax/upload'
        , upload_exts: 'gif|jpg|jpeg|png'
        , add_url: (typeof ADD_URL !== 'undefined' ? ADD_URL : CONFIG.CONTROLLER + '/add')
        , edit_url: (typeof EDIT_URL != 'undefined' ? EDIT_URL : CONFIG.CONTROLLER + '/edit')
        , delete_url: (typeof DELETE_URL != 'undefined' ? DELETE_URL : CONFIG.CONTROLLER + '/delete')
        , export_url: (typeof EXPORT_URL != 'undefined' ? EXPORT_URL : CONFIG.CONTROLLER + '/export')
    };
    let myCommon = {
        config: {
            shade: [0.02, '#000'],
        }
        , MONEY_UNIT: 100
        , typeList: null
        , getNumber: function (value, defVal) {
            if (isNaN(value)) {
                return (defVal == null ? '' : defVal);
            }
            return value;
        }
        , getNumberValue: function (dom, defVal) {
            return myCommon.getNumber(parseFloat($(dom).val()), defVal);
        }
        , getNumberText: function (dom, defVal) {
            return myCommon.getNumber(parseFloat($(dom).text()), defVal);
        }
        , getIntegerValue: function (dom, defVal) {
            return myCommon.getNumber(parseInt($(dom).val(), 10), defVal);
        }
        , getIntegerText: function (dom, defVal) {
            return myCommon.getNumber(parseInt($(dom).text(), 10), defVal);
        }
        , double2String: function (d) {
            let ret = d.toFixed(2);
            if (/\d+\.00$/.exec(ret)) {
                ret = ret.replace(".00", "");
            }
            return ret;
        }
        , timeDiff(startTime, endTime) {
            // 将时间字符串转换为 Date 对象
            let start = new Date('1970-01-01T' + startTime + 'Z'),
                end = new Date('1970-01-01T' + endTime + 'Z');
            // 计算时间差（以毫秒为单位）
            let diffMilliseconds = end - start;
            // 将毫秒转换为小时
            return myCommon.double2String(diffMilliseconds / (1000 * 60 * 60));
        }
        , openPage: function (url, param) {
            let form = '<form action="' + url + '"  target="_blank"  id="windowOpen" style="display:none">';
            for (let key in param) {
                form += '<input name="' + key + '" value="' + param[key] + '"/>';
            }
            form += '</form>';
            $('body').append(form);
            $('#windowOpen').submit();
            $('#windowOpen').remove();
        }
        , generateParams: function (arrIgnore = []) {
            let params = {};
            $('form').find('input,select').not(':button').each(function () {
                let $this = $(this);
                if ($this.attr('name') == null) {
                    return true;
                }
                if (arrIgnore.find(item => item == $this.attr('name')) != undefined) {
                    return true;
                }
                if ($this.is(':radio')) {
                } else if ($this.is(':checkbox')) {
                } else if ($this.val() != '') {
                    params[$this.attr('name')] = $this.val();
                }
            });
            return params;
        }
        , getTypeList: function (type) {
            if (myCommon.typeList == null) {
                myCommon.typeList = JSON.parse(localStorage.getItem('TYPE_LIST') || '{}');
            }
            let list = myCommon.value(myCommon.typeList, type);
            if (list == undefined) list = [];
            return list;
        }
        , changeTypeList: function (dom, typeName, fn) {
            let $this = $(dom)
                , selDefault = $this.attr('data-select-default')
                , list = myCommon.getTypeList(typeName)
                , html = [];
            if (selDefault != null) {
                html.push('<option value="">' + selDefault + '</option>');
            }
            for (let i = 0; i < list.length; i++) {
                html.push('<option value="' + list[i].value + '">' + list[i].name + '</option>');
            }
            $this.html(html.join(''));
            if (fn != null) {
                fn();
            }
            form.render('select');
        }
        , getTypeItem: function (value, type) {
            let list = myCommon.getTypeList(type), item = null;
            $.each(list, function (i, n) {
                if (n.value == value) {
                    item = n;
                    return false;
                }
            });
            return item;
        }
        , getNameInType: function (value, type) {
            let item = myCommon.getTypeItem(value, type);
            return item == null ? '' : item.name;
        }
        /**
         * 表格统计通用处理方法
         * 表格设置统计参数（totalRow: true），且的回调方法中如下处理
         * done: function (res) {
         *     myCommon.tableTotal(this, res.data, ['friend_num', 'friend_male', 'friend_female', 'friend_unknown'])
         * }
         * @param tab  表格对象
         * @param data  回调时的数据对象
         * @param fields  统计的字段名数组
         */
        , tableTotal: function (tab, data, fields) {
            let totalInfo = {}
            layui.each(fields, function (i, f) {
                totalInfo[f] = 0
            })
            layui.each(data, function (i, d) {
                layui.each(fields, function (i, f) {
                    totalInfo[f] += myCommon.getNumber(parseFloat(d[f]), 0)
                })
            })
            let total = tab.elem.next().find('.layui-table-total')
            layui.each(fields, function (i, f) {
                total.find('td[data-field="' + f + '"] .layui-table-cell').text(myCommon.double2String(totalInfo[f]))
            })
        }
        /**
         * 表格高级统计通用处理方法
         * 表格设置统计参数（totalRow: true），且的回调方法中如下处理
         * done: function (res) {
         *     myCommon.tableAdvance.total(this, res.data, {
         *          'person_num': myCommon.tableAdvance.defaultValue
         *          , 'quoted_money': myCommon.tableAdvance.moneyValue
         *      })
         * }
         * @param tab  表格对象
         * @param data  回调时的数据对象
         * @param fields  统计的字段名对象
         */
        , tableAdvance: {
            total: function (tab, data, fields) {
                let totalInfo = {}
                layui.each(fields, function (f) {
                    totalInfo[f] = 0
                })
                layui.each(data, function (i, d) {
                    layui.each(fields, function (f, fn) {
                        totalInfo[f] += fn(d, f)
                    })
                })
                let total = tab.elem.next().find('.layui-table-total')
                layui.each(fields, function (f) {
                    total.find('td[data-field="' + f + '"] .layui-table-cell').text(myCommon.double2String(totalInfo[f]))
                })
            }
            , defaultValue: function (data, f) {
                return myCommon.getNumber(parseFloat(data[f]), 0)
            }
            , moneyValue: function (data, f) {
                return myCommon.getNumber(parseFloat(data[f]), 0) / myCommon.MONEY_UNIT
            }
        }
        /**
         * 简单表格合计
         * @param tab  表格对象
         * @param fields  统计的字段名数组
         */
        , tableSimpleTotal: function (tab, fields) {
            let total, $tab = $(tab);
            $.each(fields, function (i, f) {
                total = 0;
                $tab.find('tbody td[data-field="' + f + '"]').each(function () {
                    total += myCommon.getNumberText(this, 0);
                });
                $tab.find('tfoot td[data-field="' + f + '"]').text(myCommon.double2String(total));
            });
        }
        , getSelectOption: function (dom) {
            let $this = $(dom);
            return $this.find('option[value="' + $this.val() + '"]');
        }
        , getDomVal: function (dom) {
            let val = dom.val();
            if (val == null && dom.is('[default-value]')) {
                return dom.attr('default-value');
            }
            return val;
        }
        , generateCondition: function () {
            let ret = {}, name, value;
            $('.table-search-fieldset').find('input,select').each(function () {
                name = $(this).attr('name');
                value = myCommon.getDomVal($(this));
                if (name != null && name != '' && value != null && value != '') {
                    ret[name] = value;
                }
            });
            return ret;
        }
        , convertEditor: function (dom) {
            let $this = $(dom)
                , toolbar = $this.attr('toolbar');
            if (toolbar == null) {
                toolbar = 'basic';
            }
            CKEDITOR.replace(
                $this.attr("name"),
                {
                    height: $this.height(),
                    toolbar: toolbar,
                    toolbar_basic: [
                        ['FontSize'],
                        ['TextColor', 'BGColor'],
                        ['Bold', 'Italic', 'Underline'],
                        ['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'],
                        ['NumberedList', 'BulletedList'],
                        ['Image'],
                        ['Undo', 'Redo'],
                        ['SelectAll', 'RemoveFormat'],
                        ['Maximize'],
                        ['Source']
                    ],
                    filebrowserImageUploadUrl: myCommon.url('ajax/uploadEditor'),
                });
        }
        , getLayuiTreeIds: function (arr, list) {
            if (!list) list = [];
            for (let i = 0; i < arr.length; i++) {
                let item = arr[i];
                list.push(item.id);
                let subs = item.children;
                if (subs && subs.length > 0) {
                    myCommon.getLayuiTreeIds(subs, list);
                }
            }
            return list;
        }
        , url: function (url) {
            return '/' + CONFIG.MODULE + '/' + url;
        }
        , currentUrl: function () {
            let url = window.location.href
                , idx = url.indexOf('?');
            if (idx == -1) {
                return url;
            }
            return url.substring(0, idx);
        }
        , dom2obj: function (dom, arr) {
            let ret = {};
            $.each(arr, function (i, n) {
                if (dom.attr(n) != null) {
                    ret[n] = dom.attr(n);
                }
            });
            return ret;
        }
        , datePicker: function ($dom, obj) {
            let arr = ['dateFmt', 'minDate', 'maxDate', 'skin', 'el', 'errDealMode', 'isShowClear'], picked;
            $.extend(obj, myCommon.dom2obj($dom, arr));
            if (obj.el == null) {
                if ($dom.attr('id') == null) {
                    $dom.attr('id', $dom.attr('name'));
                }
                obj.el = $dom.attr('id');
            }
            if (obj.skin == null) {
                obj.skin = 'default';
            }
            if (obj.errDealMode == null) {
                obj.errDealMode = '1';
            }
            if (obj.isShowClear == 'false') {
                obj.isShowClear = false;
            } else {
                obj.isShowClear = true;
            }
            if ($dom.attr('enabledJavaDays') != null) {
                let weeks = $dom.attr('enabledJavaDays');
                let i, arr = [];
                for (i = 1; i < 8; i++) {
                    if (weeks.indexOf(i) == -1) {
                        arr.push(i - 1);
                    }
                }
                obj.disabledDays = arr;
            }
            if ($dom.attr('onpicked') != null) {
                obj.onpicked = function () {
                    picked = $dom.attr('onpicked');
                    if (typeof (eval(picked)) == 'function') {
                        eval(picked)($dom);
                    }
                };
            }
            obj.readOnly = true;
            obj.lang = 'zh-cn';
            $dom.addClass('date-icon').focus(function () {
                WdatePicker(obj);
            });
        }
        , checkAuth: function (node, elem) {
            if ($(elem).attr('data-auth-' + node) === '1') {
                return true;
            } else {
                return false;
            }
        }
        , checkMobile: function () {
            //根据userAgent判断是否是手机
            if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|SymbianOS|Windows Phone/i.test(navigator.userAgent)) {
                return true;
            }
            //根据屏幕分辨率判断是否是手机
            if ((window.screen.width < 600 && window.screen.height < 800) || (window.screen.width < 800 && window.screen.height < 600)) {
                return true;
            }
            return false;
        }
        , param: function (param, defaultParam) {
            return param !== undefined ? param : defaultParam;
        }
        , closeCurrentPopup: function () {
            parent.layer.close(parent.layer.getFrameIndex(window.name));
        }
        , request: {
            post: function (option, ok, no, ex) {
                return myCommon.request.ajax('post', option, ok, no, ex);
            }
            , get: function (option, ok, no, ex) {
                return myCommon.request.ajax('get', option, ok, no, ex);
            }
            , ajax: function (type, option, ok, no, ex) {
                type = type || 'get';
                option.url = option.url || '';
                option.data = option.data || {};
                option.prefix = option.prefix || false;
                option.statusName = option.statusName || 'code';
                option.statusCode = option.statusCode || 0;
                ok = ok || function (res) {
                };
                no = no || function (res) {
                    let msg = res.msg == undefined ? '返回数据格式有误' : res.msg;
                    myCommon.msg.error(msg);
                    return false;
                };
                ex = ex || function (res) {
                };
                if (option.url == '') {
                    myCommon.msg.error('请求地址不能为空');
                    return false;
                }
                if (option.prefix == true) {
                    option.url = myCommon.url(option.url);
                }
                let index = null;
                if (window.hasLoading == null || window.hasLoading == true) {
                    index = myCommon.msg.loading(window.loadingMsg == null ? '加载中' : window.loadingMsg);
                }
                $.ajax({
                    url: option.url,
                    type: type,
                    contentType: "application/x-www-form-urlencoded; charset=UTF-8",
                    dataType: "json",
                    data: option.data,
                    timeout: 60000,
                    success: function (res) {
                        if (index != null) {
                            myCommon.msg.close(index);
                        }
                        if (eval('res.' + option.statusName) == option.statusCode) {
                            return ok(res);
                        } else {
                            return no(res);
                        }
                    },
                    error: function (xhr, textstatus, thrown) {
                        myCommon.msg.error('Status:' + xhr.status + '，' + xhr.statusText + '，请稍后再试！', function () {
                            ex(this);
                        });
                        return false;
                    }
                });
            }
        }
        , msg: {
            // 成功消息
            success: function (msg, callback) {
                if (callback === undefined) {
                    callback = function () {
                    }
                }
                let index = layer.msg(msg, {
                    icon: 1,
                    shade: myCommon.config.shade,
                    scrollbar: false,
                    time: 2000,
                    shadeClose: true
                }, callback);
                return index;
            }
            // 失败消息
            , error: function (msg, callback) {
                if (callback === undefined) {
                    callback = function () {
                    }
                }
                let index = layer.msg(msg, {
                    icon: 2,
                    shade: myCommon.config.shade,
                    scrollbar: false,
                    time: 3000,
                    shadeClose: true
                }, callback);
                return index;
            }
            // 警告消息框
            , alert: function (msg, callback) {
                let index = layer.alert(msg, {end: callback, scrollbar: false});
                return index;
            }
            // 对话框
            , confirm: function (msg, ok, no) {
                let index = layer.confirm(msg, {title: '操作确认', btn: ['确认', '取消']}, function () {
                    typeof ok === 'function' && ok.call(this);
                }, function () {
                    typeof no === 'function' && no.call(this);
                    self.close(index);
                });
                return index;
            }
            // 消息提示
            , tips: function (msg, time, callback) {
                let index = layer.msg(msg, {
                    time: (time || 3) * 1000,
                    shade: this.shade,
                    end: callback,
                    shadeClose: true
                });
                return index;
            }
            // 加载中提示
            , loading: function (msg, callback) {
                let index = msg ? layer.msg(msg, {
                    icon: 16,
                    scrollbar: false,
                    shade: this.shade,
                    time: 0,
                    end: callback
                }) : layer.load(2, {time: 0, scrollbar: false, shade: this.shade, end: callback});
                return index;
            }
            // 关闭消息框
            , close: function (index) {
                return layer.close(index);
            }
        }
        , open: function (title, url, clienWidth, clientHeight, isResize) {
            isResize = isResize === undefined ? true : isResize;
            if (clienWidth === undefined || clientHeight === undefined) {
                let width = document.body.clientWidth,
                    height = document.body.clientHeight;
                if (width >= 1000 && height >= 600) {
                    clienWidth = '1000px';
                    clientHeight = '600px';
                } else {
                    clienWidth = '100%';
                    clientHeight = '100%';
                }
            }
            let index = layer.open({
                title: title,
                type: 2,
                area: [clienWidth, clientHeight],
                content: url,
                maxmin: true,
                moveOut: true
            });
            if (myCommon.checkMobile() || clienWidth === undefined || clientHeight === undefined) {
                try {
                    layer.full(index);
                } catch (e) {
                }
            }
            if (isResize) {
                $(window).on("resize", function () {
                    try {
                        layer.full(index);
                    } catch (e) {
                    }
                })
            }
        }
        , showWindow: function (options) {
            let o = $.extend({
                dialogWidth: 1000,
                dialogHeight: 550,
                fnCallback: function () {
                }
            }, options || {});
            top.window.dialogArguments = o;
            top.window.returnValue = null;
            let index = top.layer.open({
                type: 2,
                title: o.title,
                maxmin: true,
                area: [o.dialogWidth + 'px', o.dialogHeight + 'px'],
                content: o.url,
                end: function () {
                    let ret = top.window.returnValue;
                    top.window.returnValue = null;
                    o.fnCallback(ret);
                }
            });
            if (myCommon.checkMobile()) {
                top.layer.full(index);
            }
            return false;
        }
        , listen: function (preposeCallback, ok, no, ex) {
            // 监听表单是否为必填项
            myCommon.api.formRequired();

            // 监听表单提交事件
            myCommon.api.formSubmit(preposeCallback, ok, no, ex);

            // 初始化图片显示以及监听上传事件
            myCommon.api.upload();
            myCommon.api.upload_old();

            // 监听富文本初始化
            myCommon.api.editor();

            // 监听下拉选择生成
            myCommon.api.select();

            // 监听多选生成
            myCommon.api.xmSelect();

            // 监听时间控件生成
            myCommon.api.date();

            myCommon.table.listenColums()

            // 初始化layui表单
            form.render();

            // 监听弹出层的打开
            $('body').on('click', '[data-open]', function () {
                let clienWidth = $(this).attr('data-width'),
                    clientHeight = $(this).attr('data-height'),
                    dataFull = $(this).attr('data-full'),
                    checkbox = $(this).attr('data-checkbox'),
                    url = $(this).attr('data-open'),
                    tableId = $(this).attr('data-table');

                if (checkbox === 'true') {
                    tableId = tableId || init.table_render_id;
                    let checkStatus = table.checkStatus(tableId),
                        data = checkStatus.data;
                    if (data.length <= 0) {
                        myCommon.msg.error('请勾选需要操作的数据');
                        return false;
                    }
                    let ids = [];
                    $.each(data, function (i, v) {
                        ids.push(v.id);
                    });
                    if (url.indexOf("?") === -1) {
                        url += '?id=' + ids.join(',');
                    } else {
                        url += '&id=' + ids.join(',');
                    }
                }

                if (dataFull === 'true') {
                    clienWidth = '100%';
                    clientHeight = '100%';
                }

                myCommon.open($(this).attr('data-title'), myCommon.url(url), clienWidth, clientHeight);
            });

            // 放大图片
            $('body').on('click', '[data-image]', function () {
                let title = $(this).attr('data-image'),
                    src = $(this).attr('src'),
                    alt = $(this).attr('alt');
                let photos = {
                    "title": title,
                    "id": Math.random(),
                    "data": [
                        {
                            "alt": alt,
                            "pid": Math.random(),
                            "src": src,
                            "thumb": src
                        }
                    ]
                };
                layer.photos({
                    photos: photos,
                    anim: 5
                });
                return false;
            });

            // 监听请求
            $('body').on('click', '[data-request]', function () {
                let title = $(this).attr('data-title'),
                    url = $(this).attr('data-request'),
                    tableId = $(this).attr('data-table'),
                    addons = $(this).attr('data-addons'),
                    checkbox = $(this).attr('data-checkbox'),
                    direct = $(this).attr('data-direct'),
                    field = $(this).attr('data-field') || 'id';

                title = title || '确定进行该操作？';

                if (direct === 'true') {
                    myCommon.msg.confirm(title, function () {
                        window.location.href = url;
                    });
                    return false;
                }

                let postData = {};
                if (checkbox === 'true') {
                    tableId = tableId || init.table_render_id;
                    let checkStatus = table.checkStatus(tableId),
                        data = checkStatus.data;
                    if (data.length <= 0) {
                        myCommon.msg.error('请勾选需要操作的数据');
                        return false;
                    }
                    let ids = [];
                    $.each(data, function (i, v) {
                        ids.push(v[field]);
                    });
                    postData[field] = ids;
                }

                if (addons !== true && addons !== 'true') {
                    url = myCommon.url(url);
                }
                tableId = tableId || init.table_render_id;
                myCommon.msg.confirm(title, function () {
                    myCommon.request.post({
                        url: url,
                        data: postData,
                    }, function (res) {
                        myCommon.msg.success(res.msg, function () {
                            table.reload(tableId);
                        });
                    })
                });
                return false;
            });
        }
        , api: {
            form: function (url, data, ok, no, ex, refreshTable, closeCurrent) {
                if (refreshTable === undefined) {
                    refreshTable = true;
                }
                if (closeCurrent === undefined) {
                    closeCurrent = true;
                }
                ok = ok || function (res) {
                    res.msg = res.msg || '';
                    myCommon.msg.success(res.msg, function () {
                        if (closeCurrent) {
                            myCommon.api.closeCurrentOpen({
                                refreshTable: refreshTable
                            });
                        } else {
                            let refreshUrl = myCommon.url(init.edit_url) + '?id=' + res.data.id;
                            console.log('刷新地址：', refreshUrl);
                            window.location = refreshUrl;
                            if (refreshTable) {
                                parent.layui.table.reload(init.table_render_id);
                            }
                        }
                    });
                    return false;
                };
                myCommon.request.post({
                    url: url
                    , data: data
                }, ok, no, ex);
                return false;
            }
            , closeCurrentOpen: function (option) {
                option = option || {};
                option.refreshTable = option.refreshTable || false;
                option.refreshFrame = option.refreshFrame || false;
                if (option.refreshTable === true) {
                    option.refreshTable = init.table_render_id;
                }
                let index = parent.layer.getFrameIndex(window.name);
                parent.layer.close(index);
                if (option.refreshTable !== false) {
                    parent.layui.table.reload(option.refreshTable);
                }
                if (option.refreshFrame) {
                    parent.location.reload();
                }
                return false;
            }
            , refreshFrame: function () {
                parent.location.reload();
                return false;
            }
            , refreshTable: function (tableName) {
                tableName = tableName || 'currentTable';
                table.reload(tableName);
            }
            , formRequired: function () {
                form.verify({
                    onlyNumber: function (value) {
                        if (value != '' && isNaN(value))
                            return '只能填写数字';
                    }
                    , onlyInteger: function (value) {
                        if (value != '' && !/^\d+$/.exec(value))
                            return '只能填写整数';
                    }
                });

                $('input[money_convert]').each(function () {
                    let value = myCommon.getIntegerValue($('#' + $(this).attr('money_convert')));
                    if (value === '') {
                        $(this).val('');
                    } else {
                        $(this).val(value / myCommon.MONEY_UNIT);
                    }
                });

                let verifyList = document.querySelectorAll("[lay-verify]");
                if (verifyList.length > 0) {
                    $.each(verifyList, function (i, v) {
                        let verifys = $(this).attr('lay-verify').split('|');
                        // todo 必填项处理
                        if ($.inArray('required', verifys) != -1) {
                            let label = $(this).parent().prev();
                            if (label.is('label') && !label.hasClass('required')) {
                                label.addClass('required');
                            }
                            if ($(this).attr('lay-reqtext') === undefined && $(this).attr('placeholder') !== undefined) {
                                $(this).attr('lay-reqtext', $(this).attr('placeholder'));
                            }
                            if ($(this).attr('placeholder') === undefined && $(this).attr('lay-reqtext') !== undefined) {
                                $(this).attr('placeholder', $(this).attr('lay-reqtext'));
                            }
                        }
                    });
                }
            }
            , formSubmit: function (preposeCallback, ok, no, ex) {
                let formList = document.querySelectorAll("[lay-submit]");

                // 表单提交自动处理
                if (formList.length > 0) {
                    $.each(formList, function (i, v) {
                        let filter = $(this).attr('lay-filter'),
                            type = $(this).attr('data-type'),
                            refresh = $(this).attr('data-refresh'),
                            closeCurrent = $(this).attr('data-close'),
                            url = $(this).attr('lay-submit');
                        // 表格搜索不做自动提交
                        if (type === 'tableSearch') {
                            return false;
                        }
                        // 判断是否需要刷新表格
                        if (refresh === 'false') {
                            refresh = false;
                        } else {
                            refresh = true;
                        }
                        if (closeCurrent === 'false') {
                            closeCurrent = false;
                        } else {
                            closeCurrent = true;
                        }
                        // 自动添加layui事件过滤器
                        if (filter === undefined || filter === '') {
                            filter = 'save_form_' + (i + 1);
                            $(this).attr('lay-filter', filter)
                        }
                        if (url === undefined || url === '' || url === null) {
                            url = window.location.href;
                        } else {
                            url = myCommon.url(url);
                        }
                        form.on('submit(' + filter + ')', function (data) {
                            let dataField = data.field;

                            // 富文本数据处理
                            let editorList = document.querySelectorAll(".editor");
                            if (editorList.length > 0) {
                                $.each(editorList, function (i, v) {
                                    let name = $(this).attr("name");
                                    dataField[name] = CKEDITOR.instances[name].getData();
                                });
                            }

                            // xm-select必填处理
                            let ret = true;
                            $('[data-xm-select-required]').each(function () {
                                let name = $(this).attr('id')
                                    , val = dataField[name];
                                if (val === undefined || val === '' || val === null) {
                                    myCommon.msg.error($(this).attr('data-xm-select-required'));
                                    ret = false;
                                    return false;
                                }
                            });
                            if (!ret) {
                                return false;
                            }

                            //上传文件处理
                            ret = true;
                            $('.upload-image,.upload-file').each(function () {
                                let $dom = $(this), cfg = $dom.data(), sb = []
                                    , direct = (typeof (cfg.direct) != 'undefined');
                                $dom.find('.item').each(function () {
                                    sb.push($(this).data(direct ? 'url' : 'md5'));
                                });
                                if (typeof (cfg.required) != 'undefined' && sb.length == 0) {
                                    myCommon.msg.error(cfg.required);
                                    ret = false;
                                    return false;
                                }
                                dataField[cfg.name] = sb.join(',');
                            });
                            if (!ret) {
                                return false;
                            }

                            //金额处理
                            $('input[money_convert]').each(function () {
                                let value = myCommon.getNumberValue(this);
                                if (value === '') {
                                    dataField[$(this).attr('money_convert')] = '';
                                } else {
                                    dataField[$(this).attr('money_convert')] = (value * myCommon.MONEY_UNIT).toFixed(0);
                                }
                            });

                            if (typeof preposeCallback === 'function') {
                                dataField = preposeCallback(dataField);
                                if (dataField === false) {
                                    return false;
                                }
                            }
                            myCommon.api.form(url, dataField, ok, no, ex, refresh, closeCurrent);

                            return false;
                        });
                    });
                }
            }
            , upload: function () {
                $('.upload-image,.upload-file').each(function () {
                    let $dom = $(this), isImage = $dom.is('.upload-image')
                        , cfg = $dom.data(), sb = [];
                    let exts = cfg.exts || (isImage ? 'gif|jpg|jpeg|png' : 'pdf|doc|docx|xls|xlsx|ppt|pptx')
                        , multiple = (typeof (cfg.multiple) != 'undefined')
                        , direct = (typeof (cfg.direct) != 'undefined');
                    //生成上传按钮
                    sb.push('<div>');
                    sb.push('<a id="upload_' + cfg.name + '" class="layui-btn layui-btn-sm">');
                    sb.push('<i class="fa fa-upload"></i>上传</a>');
                    sb.push('<i class="upload-format">上传文件格式:' + exts.replaceAll('|', ',') + '</i></div>');
                    sb.push('<div class="upload-list" id="list_' + cfg.name + '"></div>');
                    $dom.append(sb.join(''));
                    //上传按钮绑定事件
                    upload.render({
                        elem: '#upload_' + cfg.name
                        , url: myCommon.url('ajax/upload')
                        , multiple: multiple
                        , accept: 'file'
                        , exts: exts
                        , done: function (res) {
                            if (res.code == 0) {
                                if (!multiple) {
                                    $('#list_' + cfg.name).find('.item').remove();
                                }
                                let sb = ['<div class="item" data-md5="' + res.data.md5 + '" data-url="' + res.data.url + '">'];
                                sb.push('<a target="_blank" href="' + res.data.url + '">');
                                if (isImage) {
                                    sb.push('<img src="' + res.data.url + '" alt="' + res.data.name + '"/>');
                                } else {
                                    sb.push(res.data.name);
                                }
                                sb.push('</a>');
                                sb.push('<i class="fa fa-close" onclick="return removeUploadItem(this)"></i></div>');
                                $('#list_' + cfg.name).append(sb.join(''));
                            } else {
                                myCommon.msg.error(res.msg);
                            }
                        }
                    });
                    // 获取默认的上传内容
                    sb = [];
                    if (direct) {
                        $.each(cfg.value.split(','), function (i, n) {
                            sb.push('<div class="item" data-url="' + n + '">');
                            sb.push('<a target="_blank" href="' + n + '">');
                            if (isImage) {
                                sb.push('<img src="' + n + '"/>');
                            } else {
                                sb.push(n);
                            }
                            sb.push('</a>');
                            sb.push('<i class="fa fa-close" onclick="return removeUploadItem(this)"></i></div>');
                        });
                        $('#list_' + cfg.name).append(sb.join(''));
                    } else if (cfg.value != '') {
                        myCommon.request.get({
                            url: 'system.uploadfile/select'
                            , data: {md5: cfg.value}
                            , prefix: true
                        }, function (res) {
                            if (res.code == 0) {
                                $.each(res.data, function (i, n) {
                                    sb.push('<div class="item" data-md5="' + n.md5 + '" data-url="' + n.url + '">');
                                    sb.push('<a target="_blank" href="' + n.url + '">');
                                    if (isImage) {
                                        sb.push('<img src="' + n.url + '" alt="' + n.name + '"/>');
                                    } else {
                                        sb.push(n.name);
                                    }
                                    sb.push('</a>');
                                    sb.push('<i class="fa fa-close" onclick="return removeUploadItem(this)"></i></div>');
                                });
                                $('#list_' + cfg.name).append(sb.join(''));
                            }
                        });
                    }
                });
            }
            , upload_old: function () {
                let uploadList = document.querySelectorAll("[data-upload]");
                let uploadSelectList = document.querySelectorAll("[data-upload-select]");

                if (uploadList.length > 0) {
                    $.each(uploadList, function (i, v) {
                        let exts = $(this).attr('data-upload-exts'),
                            uploadName = $(this).attr('data-upload'),
                            uploadNumber = $(this).attr('data-upload-number'),
                            uploadSign = $(this).attr('data-upload-sign'),
                            uploadPrefix = $(this).attr('data-upload-prefix');
                        exts = exts || init.upload_exts;
                        uploadNumber = uploadNumber || 'one';
                        uploadSign = uploadSign || '|';
                        uploadPrefix = uploadPrefix || 'up';
                        let elem = "input[name='" + uploadName + "']",
                            uploadElem = this;

                        // 监听上传事件
                        upload.render({
                            elem: this,
                            url: myCommon.url(init.upload_url),
                            accept: 'file',
                            exts: exts,
                            data: {prefix: uploadPrefix},
                            // 让多图上传模式下支持多选操作
                            multiple: (uploadNumber !== 'one') ? true : false,
                            done: function (res) {
                                if (res.code === 0) {
                                    let url = res.data.url;
                                    if (uploadNumber !== 'one') {
                                        let oldUrl = $(elem).val();
                                        if (oldUrl !== '') {
                                            url = oldUrl + uploadSign + url;
                                        }
                                    }
                                    $(elem).val(url);
                                    $(elem).trigger("input");
                                    myCommon.msg.success(res.msg);
                                } else {
                                    myCommon.msg.error(res.msg);
                                }
                                return false;
                            }
                        });

                        // 监听上传input值变化
                        $(elem).bind("input propertychange", function (event) {
                            let urlString = $(this).val(),
                                urlArray = urlString.split(uploadSign),
                                uploadIcon = $(uploadElem).attr('data-upload-icon');
                            uploadIcon = uploadIcon || "file";

                            $('#bing-' + uploadName).remove();
                            if (urlString.length > 0) {
                                let parant = $(this).parent('div');
                                let liHtml = '';
                                $.each(urlArray, function (i, v) {
                                    liHtml += '<li>';
                                    if (v.lastIndexOf('.mp4') != -1) {
                                        liHtml += '<a><video width="320" controls><source src="' + v + '" type="video/mp4"></video></a>';
                                    } else {
                                        liHtml += '<a><img src="' + v + '" data-image></a>';
                                    }
                                    liHtml += '<small class="uploads-delete-tip bg-red badge" data-upload-delete="' + uploadName + '" data-upload-url="' + v + '" data-upload-sign="' + uploadSign + '">×</small>';
                                    liHtml += '</li>\n';
                                });
                                parant.after('<ul id="bing-' + uploadName + '" class="layui-input-block layuimini-upload-show">\n' + liHtml + '</ul>');
                            }

                        });

                        // 非空初始化图片显示
                        if ($(elem).val() !== '') {
                            $(elem).trigger("input");
                        }
                    });

                    // 监听上传文件的删除事件
                    $('body').on('click', '[data-upload-delete]', function () {
                        let uploadName = $(this).attr('data-upload-delete'),
                            deleteUrl = $(this).attr('data-upload-url'),
                            sign = $(this).attr('data-upload-sign');
                        let confirm = myCommon.msg.confirm('确定删除？', function () {
                            let elem = "input[name='" + uploadName + "']";
                            let currentUrl = $(elem).val();
                            let url = '';
                            if (currentUrl !== deleteUrl) {
                                url = currentUrl.replace(sign + deleteUrl, '');
                                $(elem).val(url);
                                $(elem).trigger("input");
                            } else {
                                $(elem).val(url);
                                $('#bing-' + uploadName).remove();
                            }
                            myCommon.msg.close(confirm);
                        });
                        return false;
                    });
                }

                if (uploadSelectList.length > 0) {
                    $.each(uploadSelectList, function (i, v) {
                        let exts = $(this).attr('data-upload-exts'),
                            uploadName = $(this).attr('data-upload-select'),
                            uploadNumber = $(this).attr('data-upload-number'),
                            uploadSign = $(this).attr('data-upload-sign');
                        exts = exts || init.upload_exts;
                        uploadNumber = uploadNumber || 'one';
                        uploadSign = uploadSign || '|';
                        let selectCheck = uploadNumber === 'one' ? 'radio' : 'checkbox';
                        let elem = "input[name='" + uploadName + "']",
                            uploadElem = $(this).attr('id');

                        tableSelect.render({
                            elem: "#" + uploadElem,
                            checkedKey: 'id',
                            searchType: 'more',
                            searchList: [
                                {searchKey: 'title', searchPlaceholder: '请输入文件名'},
                            ],
                            table: {
                                url: myCommon.url('ajax/getUploadFiles'),
                                cols: [[
                                    {type: selectCheck},
                                    {field: 'id', title: 'ID'},
                                    {
                                        field: 'url',
                                        minWidth: 80,
                                        title: '图片信息',
                                        imageHeight: 40,
                                        align: "center",
                                        templet: myCommon.table.image
                                    },
                                    {field: 'original_name', width: 150, title: '文件原名', align: "center"},
                                    {field: 'mime_type', width: 120, title: 'mime类型', align: "center"},
                                    {field: 'create_time', width: 200, title: '创建时间', align: "center"},
                                ]]
                            },
                            done: function (e, data) {
                                let urlArray = [];
                                $.each(data.data, function (index, val) {
                                    urlArray.push(val.url)
                                });
                                let url = urlArray.join(uploadSign);
                                myCommon.msg.success('选择成功', function () {
                                    $(elem).val(url);
                                    $(elem).trigger("input");
                                });
                            }
                        })

                    });
                }
            }
            , editor: function () {
                let editorList = document.querySelectorAll(".editor");
                if (editorList.length > 0) {
                    $.each(editorList, function (i, v) {
                        myCommon.convertEditor(this);
                    });
                }
            }
            , select: function () {
                let selectList = document.querySelectorAll("[data-select-type]");
                $.each(selectList, function () {
                    let type = $(this).attr('data-select-type')
                        , selDefault = $(this).attr('data-select-default')
                        , list = myCommon.getTypeList(type)
                        , value = 0
                        , html = [];
                    if ($(this).attr('init-value') != null) {
                        value = parseInt($(this).attr('init-value'));
                    } else if ($(this).attr('default-value') != null) {
                        value = parseInt($(this).attr('default-value'));
                    }
                    if (selDefault != null) {
                        html.push('<option value="">' + selDefault + '</option>');
                    }
                    for (let i = 0; i < list.length; i++) {
                        html.push('<option value="' + list[i].value + '"'
                            + (list[i].value == value ? ' selected' : '')
                            + '>' + list[i].name + '</option>');
                    }
                    $(this).html(html.join(''));
                });

                // 下拉框默认值处理
                let selList = document.querySelectorAll("[default-value]");
                $.each(selList, function () {
                    if ($(this).is('[data-select-type]')) {
                        return true;
                    }
                    $(this).find('option[value="' + $(this).attr('default-value') + '"]').attr('selected', 'selected');
                });
            }
            , xmSelect: function () {
                let select = $('.xm-select-hide');
                if (select.size() > 0 && typeof (xmSelect) == 'undefined') {
                    myCommon.msg.error('请先引入xm-select.js');
                    return false;
                }
                select.each(function () {
                    let config = $(this).data(), data = [], param = {}, sb = [];
                    sb.push('<div id="' + config.name + '"');
                    if (typeof (config.required) != 'undefined') {
                        sb.push(' data-xm-select-required="' + config.required + '"');
                        $(this).closest('.layui-form-item').find('.layui-form-label').addClass('required');
                    }
                    sb.push('></div>');
                    $(this).before(sb.join(''));
                    param['el'] = '#' + config.name;
                    param['name'] = config.name;
                    if (typeof (config.value) == 'number') {
                        param['initValue'] = [config.value];
                    } else if (typeof (config.value) == 'string' && config.value != '') {
                        param['initValue'] = config.value.split(',');
                    }
                    if (typeof (config.tips) == 'string' && config.tips != '') {
                        param['tips'] = config.tips;
                    }
                    if (typeof (config.radio) != 'undefined') {
                        param['radio'] = true;
                        param['clickClose'] = true;
                    }
                    if (typeof (config.filterable) != 'undefined') {
                        param['filterable'] = true;
                    }
                    $(this).find('div').each(function () {
                        data.push({name: $(this).text(), value: $(this).data('id')});
                    });
                    param['data'] = data;
                    xmSelect.render(param);
                })
            }
            , date: function () {
                $('.cssDateTime').each(function () {
                    myCommon.datePicker($(this), {doubleCalendar: true, dateFmt: 'yyyy-MM-dd HH:mm'});
                });
                $('.cssDate').each(function () {
                    myCommon.datePicker($(this), {doubleCalendar: true, dateFmt: 'yyyy-MM-dd'});
                });
                $('.cssMonthDay').each(function () {
                    myCommon.datePicker($(this), {doubleCalendar: true, dateFmt: 'MM-dd'});
                });
                $('.cssSingleDate').each(function () {
                    myCommon.datePicker($(this), {dateFmt: 'yyyy-MM-dd'});
                });
                $('.cssMonth').each(function () {
                    myCommon.datePicker($(this), {dateFmt: 'yyyy-MM'});
                });
                $('.cssYear').each(function () {
                    myCommon.datePicker($(this), {dateFmt: 'yyyy'});
                });
                $('.cssTime').each(function () {
                    let $this = $(this);
                    $this.addClass('date-icon').attr('readOnly', 'readOnly');
                    let picked = $this.attr('onpicked');
                    laydate.render({
                        elem: this,
                        trigger: 'click',
                        type: 'time',
                        format: 'HH:mm',
                        done: function (value, date) {
                            setTimeout(function () {
                                if (typeof (eval(picked)) == 'function') {
                                    eval(picked)($this, value, date);
                                }
                            }, 50);
                        }
                    });
                });

                let dateList = document.querySelectorAll("[data-date]");
                if (dateList.length > 0) {
                    $.each(dateList, function (i, v) {
                        let format = $(this).attr('data-date'),
                            type = $(this).attr('data-date-type'),
                            range = $(this).attr('data-date-range');
                        if (type === undefined || type === '' || type === null) {
                            type = 'date';
                        }
                        let options = {
                            elem: this,
                            type: type,
                        };
                        if (format !== undefined && format !== '' && format !== null) {
                            options['format'] = format;
                        }
                        if (range !== undefined) {
                            if (range === null || range === '') {
                                range = '-';
                            }
                            options['range'] = range;
                        }
                        laydate.render(options);
                    });
                }
            }
        }
        , value: function (data, field) {
            try {
                return eval("data." + field);
            } catch (e) {
                return undefined;
            }
        }
        , nullToEmpty: function (val) {
            return val == null ? '' : val;
        }
        , table: {
            param: {}
            , render: function (options) {
                options.init = options.init || init;
                options.elem = options.elem || options.init.table_elem;
                options.id = options.id || options.init.table_render_id;
                options.layFilter = options.id + '_LayFilter';
                options.autoSort = options.autoSort !== undefined ? options.autoSort : false;
                options.url = options.url || myCommon.currentUrl();
                options.page = options.page !== undefined ? options.page : true;
                options.search = options.search !== undefined ? options.search : true;
                options.limit = options.limit || 15;
                options.limits = options.limits || [15, 30, 50, 100, 300, 500, 1000, 100000];
                options.cols = options.cols || [];

                const key = location.href;
                for (let i = 0; i < options.cols[0].length; i++) {
                    if (options.cols[0][i].title != undefined && localStorage.hasOwnProperty(key + options.cols[0][i].title)) {
                        options.cols[0][i].hide = true;
                    }
                }

                let bar = ['filter'];
                if (!myCommon.checkMobile()) {
                    if (myCommon.checkAuth('print', options.elem)) {
                        bar.push('print');
                    }
                    if (myCommon.checkAuth('exports', options.elem)) {
                        bar.push('exports');
                    }
                }
                if (!(options.defaultToolbar === undefined && !options.search)) {
                    bar.push({
                        title: '搜索',
                        layEvent: 'TABLE_SEARCH',
                        icon: 'layui-icon-search',
                        extend: 'data-table-id="' + options.id + '"'
                    });
                }
                options.defaultToolbar = bar;

                // 初始化表格lay-filter
                $(options.elem).attr('lay-filter', options.layFilter);

                // 初始化表格左上方工具栏
                options.toolbar = options.toolbar || ['refresh', 'add', 'delete', 'export'];
                options.toolbar = myCommon.table.renderToolbar(options.toolbar, options.elem, options.id, options.init);

                // 初始化表格
                let newTable = table.render(options);

                // 监听表格工具栏事件
                myCommon.table.listenToolbar(options.layFilter, options.id);

                // 监听搜索框提交事件
                myCommon.table.listenSearchSubmit(options.layFilter, options.id);

                // 监听排序提交事件
                myCommon.table.listenSort(options.layFilter, options.id);
                return newTable;
            }
            , renderToolbar: function (data, elem, tableId, init) {
                data = data || [];
                let toolbarHtml = '';
                $.each(data, function (i, v) {
                    if (v === 'refresh') {
                        toolbarHtml += ' <button class="layui-btn layui-btn-sm layuimini-btn-primary" data-table-refresh="' + tableId + '"><i class="fa fa-refresh"></i> </button>\n';
                    } else if (v === 'add') {
                        if (myCommon.checkAuth('add', elem)) {
                            toolbarHtml += '<button class="layui-btn layui-btn-normal layui-btn-sm" data-open="' + init.add_url + '" data-title="添加"><i class="fa fa-plus"></i> 添加</button>\n';
                        }
                    } else if (v === 'delete') {
                        if (myCommon.checkAuth('delete', elem)) {
                            toolbarHtml += '<button class="layui-btn layui-btn-sm layui-btn-danger" data-url="' + init.delete_url + '" data-table-delete="' + tableId + '"><i class="fa fa-trash-o"></i> 删除</button>\n';
                        }
                    } else if (v === 'export') {
                        if (myCommon.checkAuth('export', elem)) {
                            toolbarHtml += '<button class="layui-btn layui-btn-sm layui-btn-success" data-url="' + init.export_url + '" data-table-export="' + tableId + '"><i class="fa fa-file-excel-o"></i> 导出</button>\n';
                        }
                    } else if (typeof v === "object") {
                        v.class = v.class || '';
                        v.icon = v.icon || '';
                        v.auth = v.auth || '';
                        v.url = v.url || '';
                        v.method = v.method || 'open';
                        v.title = v.title || v.text;
                        v.text = v.text || v.title;
                        v.extend = v.extend || '';
                        v.checkbox = v.checkbox || false;
                        if (myCommon.checkAuth(v.auth, elem)) {
                            toolbarHtml += myCommon.table.buildToolbarHtml(v, tableId);
                        }
                    }
                });
                return '<div>' + toolbarHtml + '</div>';
            }
            , buildToolbarHtml: function (toolbar, tableId) {
                let html = '';
                toolbar.class = toolbar.class || '';
                toolbar.icon = toolbar.icon || '';
                toolbar.auth = toolbar.auth || '';
                toolbar.url = toolbar.url || '';
                toolbar.extend = toolbar.extend || '';
                toolbar.method = toolbar.method || 'open';
                toolbar.field = toolbar.field || 'id';
                toolbar.title = toolbar.title || toolbar.text;
                toolbar.text = toolbar.text || toolbar.title;
                toolbar.checkbox = toolbar.checkbox || false;

                let formatToolbar = toolbar;
                formatToolbar.icon = formatToolbar.icon !== '' ? '<i class="' + formatToolbar.icon + '"></i> ' : '';
                formatToolbar.class = formatToolbar.class !== '' ? 'class="' + formatToolbar.class + '" ' : '';
                if ('function' == typeof toolbar.fn) {
                    formatToolbar.method = toolbar.fn(toolbar);
                } else if (toolbar.method === 'open') {
                    formatToolbar.method = formatToolbar.method !== '' ? 'data-open="' + formatToolbar.url + '" data-title="' + formatToolbar.title + '" ' : '';
                } else {
                    formatToolbar.method = formatToolbar.method !== '' ? 'data-request="' + formatToolbar.url + '" data-title="' + formatToolbar.title + '" ' : '';
                }
                formatToolbar.checkbox = toolbar.checkbox ? ' data-checkbox="true" ' : '';
                formatToolbar.tableId = tableId !== undefined ? ' data-table="' + tableId + '" ' : '';
                html = '<button ' + formatToolbar.class + formatToolbar.method + formatToolbar.extend + formatToolbar.checkbox + formatToolbar.tableId + '>' + formatToolbar.icon + formatToolbar.text + '</button>';

                return html;
            }
            , listenColums: function () {
                // 选择需要观察变动的节点
                const targetNode = document.getElementsByClassName('layui-table-tool-self')[0];
                if (targetNode != undefined) {
                    const key = location.href;
                    // 当观察到变动时执行的回调函数
                    const callback = function (mutationsList) {
                        for (let mutation of mutationsList) {
                            if (mutation.type === 'attributes') {
                                // 组装缓存key
                                let localkey = key + mutation.target.innerText;
                                //判断value值
                                if (mutation.target.classList[2] != undefined) {
                                    //"layui-form-checked"  复选框是已选择的,说明此列是在表中显示的
                                    window.localStorage.removeItem(localkey);
                                } else {
                                    //没被选择,说明此列不在table中显示
                                    window.localStorage.setItem(localkey, 1);
                                }
                            }
                        }
                    };

                    // 创建一个观察器实例并传入回调函数
                    const observer = new MutationObserver(callback);
                    // 以上述配置开始观察目标节点  观察器的配置（需要观察什么变动）
                    observer.observe(targetNode, {attributes: true, childList: true, subtree: true});
                }
            }
            , listenToolbar: function (layFilter, tableId) {
                //搜索表单显示隐藏
                table.on('toolbar(' + layFilter + ')', function (obj) {
                    switch (obj.event) {
                        case 'TABLE_SEARCH':
                            let searchFieldsetId = 'searchFieldset_' + tableId;
                            let _that = $("#" + searchFieldsetId);
                            if (_that.hasClass("layui-hide")) {
                                _that.removeClass('layui-hide');
                            } else {
                                _that.addClass('layui-hide');
                            }
                            break;
                    }
                });

                // 监听动态表格刷新
                $('body').on('click', '[data-table-refresh]', function () {
                    let tableId = $(this).attr('data-table-refresh');
                    if (tableId === undefined || tableId === '' || tableId == null) {
                        tableId = init.table_render_id;
                    }
                    table.reload(tableId);
                });

                // excel导出
                $('body').on('click', '[data-table-export]', function () {
                    let tableId = $(this).attr('data-table-export'),
                        url = $(this).attr('data-url');
                    let index = myCommon.msg.confirm('根据查询进行导出，确定导出？', function () {
                        window.location = myCommon.url(url) + '?' + $.param(myCommon.generateCondition());
                        layer.close(index);
                    });
                });

                // 数据表格多删除
                $('body').on('click', '[data-table-delete]', function () {
                    let tableId = $(this).attr('data-table-delete'),
                        url = $(this).attr('data-url');
                    tableId = tableId || init.table_render_id;
                    url = url !== undefined ? myCommon.url(url) : window.location.href;
                    let checkStatus = table.checkStatus(tableId),
                        data = checkStatus.data;
                    if (data.length <= 0) {
                        myCommon.msg.error('请勾选需要删除的数据');
                        return false;
                    }
                    let ids = [];
                    $.each(data, function (i, v) {
                        ids.push(v.id);
                    });
                    myCommon.msg.confirm('确定删除？', function () {
                        myCommon.request.post({
                            url: url,
                            data: {
                                id: ids
                            },
                        }, function (res) {
                            myCommon.msg.success(res.msg, function () {
                                table.reload(tableId);
                            });
                        });
                    });
                    return false;
                });
            }
            , buildOperatHtml: function (operat, data) {
                let html = '';
                operat.class = operat.class || '';
                operat.icon = operat.icon || '';
                operat.auth = operat.auth || '';
                operat.url = operat.url || '';
                operat.extend = operat.extend || '';
                operat.method = operat.method || 'open';
                operat.field = operat.field || 'id';
                operat.title = operat.title || operat.text;
                operat.text = operat.text || operat.title;

                let formatOperat = operat;
                formatOperat.icon = formatOperat.icon !== '' ? '<i class="' + formatOperat.icon + '"></i> ' : '';
                formatOperat.class = formatOperat.class !== '' ? 'class="' + formatOperat.class + '" ' : '';
                if ('function' == typeof operat.fn) {
                    formatOperat.method = operat.fn(data, operat);
                } else if (operat.method === 'open') {
                    formatOperat.method = formatOperat.method !== '' ? 'data-open="' + formatOperat.url + '" data-title="' + formatOperat.title + '" ' : '';
                } else {
                    formatOperat.method = formatOperat.method !== '' ? 'data-request="' + formatOperat.url + '" data-title="' + formatOperat.title + '" ' : '';
                }
                html = '<a ' + formatOperat.class + formatOperat.method + formatOperat.extend + '>' + formatOperat.icon + formatOperat.text + '</a>';

                return html;
            }
            , toolSpliceUrl(url, field, data) {
                url = url.indexOf("?") !== -1 ? url + '&' + field + '=' + data[field] : url + '?' + field + '=' + data[field];
                return url;
            }
            , tool: function (data, option) {
                option.operat = option.operat || ['edit', 'delete'];
                let elem = init.table_elem;
                let html = '';
                $.each(option.operat, function (i, item) {
                    if (typeof item === 'string') {
                        switch (item) {
                            case 'edit':
                                var operat = {
                                    class: 'layui-btn layui-btn-success layui-btn-xs',
                                    method: 'open',
                                    field: 'id',
                                    icon: '',
                                    text: '编辑',
                                    title: '编辑信息',
                                    auth: 'edit',
                                    url: init.edit_url,
                                    extend: ""
                                };
                                operat.url = myCommon.table.toolSpliceUrl(operat.url, operat.field, data);
                                if (myCommon.checkAuth(operat.auth, elem)) {
                                    html += myCommon.table.buildOperatHtml(operat, data);
                                }
                                break;
                            case 'delete':
                                var operat = {
                                    class: 'layui-btn layui-btn-danger layui-btn-xs',
                                    method: 'get',
                                    field: 'id',
                                    icon: '',
                                    text: '删除',
                                    title: '确定删除？',
                                    auth: 'delete',
                                    url: init.delete_url,
                                    extend: ""
                                };
                                operat.url = myCommon.table.toolSpliceUrl(operat.url, operat.field, data);
                                if (myCommon.checkAuth(operat.auth, elem)) {
                                    html += myCommon.table.buildOperatHtml(operat, data);
                                }
                                break;
                        }

                    } else if (typeof item === 'object') {
                        $.each(item, function (i, operat) {
                            operat.class = operat.class || '';
                            operat.icon = operat.icon || '';
                            operat.auth = operat.auth || '';
                            operat.url = operat.url || '';
                            operat.method = operat.method || 'open';
                            operat.field = operat.field || 'id';
                            operat.title = operat.title || operat.text;
                            operat.text = operat.text || operat.title;
                            operat.extend = operat.extend || '';
                            operat.url = myCommon.table.toolSpliceUrl(operat.url, operat.field, data);
                            if (myCommon.checkAuth(operat.auth, elem)) {
                                html += myCommon.table.buildOperatHtml(operat, data);
                            }
                        });
                    }
                });
                return html;
            }
            , listenSearchSubmit: function (layFilter, tableId) {
                form.on('submit(search_' + tableId + ')', function (data) {
                    //金额处理
                    $('input[money_convert]').each(function () {
                        let value = myCommon.getNumberValue(this);
                        if (value === '') {
                            data.field[$(this).attr('money_convert')] = '';
                        } else {
                            data.field[$(this).attr('money_convert')] = (value * myCommon.MONEY_UNIT).toFixed(0);
                        }
                    });

                    table.reload(tableId, {
                        page: {
                            curr: 1
                        }
                        , where: data.field
                    });
                    return false;
                });
            }
            , listenSort: function (layFilter, tableId) {
                table.on('sort(' + layFilter + ')', function (obj) {
                    table.reload(tableId, {
                        initSort: obj
                        , where: {
                            field: obj.field
                            , order: obj.type
                        }
                    });
                });
            }
            , image: function (data, option) {
                option.imageWidth = option.imageWidth || 200;
                option.imageHeight = option.imageHeight || 40;
                option.imageSplit = option.imageSplit || '|';
                option.imageJoin = option.imageJoin || '<br>';
                option.title = option.title || option.field;
                let title = data[option.title]
                    , value = myCommon.value(data, option.field);
                if (value === undefined) {
                    if (value.lastIndexOf('.mp4') != -1) {
                        return '<video width="' + option.imageWidth + '" controls><source src="' + value + '" type="video/mp4"></video>';
                    } else {
                        return '<img style="max-width: ' + option.imageWidth + 'px; max-height: ' + option.imageHeight + 'px;" src="' + value + '" data-image="' + title + '">';
                    }
                } else {
                    let values = value.split(option.imageSplit),
                        valuesHtml = [];
                    values.forEach((value, index) => {
                        if (value.lastIndexOf('.mp4') != -1) {
                            valuesHtml.push('<video width="' + option.imageWidth + '" controls><source src="' + value + '" type="video/mp4"></video>');
                        } else {
                            valuesHtml.push('<img style="max-width: ' + option.imageWidth + 'px; max-height: ' + option.imageHeight + 'px;" src="' + value + '" data-image="' + title + '">');
                        }
                    });
                    return valuesHtml.join(option.imageJoin);
                }
            }
            , url: function (data, option) {
                let value = myCommon.value(data, option.field);
                return '<a class="layuimini-table-url" href="' + value + '" target="_blank" class="label bg-green">' + value + '</a>';
            }
            , link: function (data, option) {
                let url = myCommon.value(data, option.url), value = myCommon.value(data, option.field);
                if (url == undefined || url == '') return value;
                return '<a class="layuimini-table-link" href="' + url + '" target="_blank">' + value + '</a>';
            }
            , dialog: function (data, option) {
                let value = myCommon.value(data, option.field)
                    , id = myCommon.value(data, 'id');
                return '<a data-open="' + option.url + '?id=' + id + '" data-title="查看">' + value + '</a>';
            }
            , switch: function (data, option) {
                let value = myCommon.value(data, option.field);
                option.filter = option.filter || option.field || null;
                option.checked = option.checked || 1;
                option.tips = option.tips || '开|关';
                let checked = value === option.checked ? 'checked' : '';
                return laytpl('<input type="checkbox" name="' + option.field + '" value="' + data.id + '" lay-skin="switch" lay-text="' + option.tips + '" lay-filter="' + option.filter + '" ' + checked + ' >').render(data);
            }
            , type: function (data, option) {
                let value = myCommon.value(data, option.field)
                    , list = myCommon.getTypeList(option.typeList);
                for (let i = 0; i < list.length; i++) {
                    if (list[i].value == value) {
                        return '<span class="' + list[i].clazz + '">' + list[i].name + '</span>';
                    }
                }
                return '';
            }
            , multiType: function (data, option) {
                let value = myCommon.value(data, option.field)
                    , list = myCommon.getTypeList(option.typeList)
                    , ret = [];
                for (let i = 0; i < list.length; i++) {
                    if (value.indexOf(list[i].value) != -1) {
                        ret.push('<span class="' + list[i].clazz + '">' + list[i].name + '</span>');
                    }
                }
                return ret.join('');
            }
            , price: function (data, option) {
                return '<span>￥' + myCommon.table.fn(data, option) + '</span>';
            }
            , money: function (data, option) {
                let value = myCommon.getNumber(parseInt(myCommon.value(data, option.field), 10));
                if (value != '') {
                    value = value / myCommon.MONEY_UNIT;
                }
                return value;
            }
            , trimMoney: function (data, option) {
                return myCommon.value(data, option.field).replace('.00', '');
            }
            , percent: function (data, option) {
                return myCommon.table.fn(data, option) + '%';
            }
            , icon: function (data, option) {
                return '<i class="' + myCommon.table.fn(data, option) + '"></i>';
            }
            , text: function (data, option) {
                return '<span class="line-limit-length">' + myCommon.table.fn(data, option) + '</span>';
            }
            , nl2br: function (data, option) {
                let value = myCommon.value(data, option.field), reg = new RegExp('\n', 'g');
                return value.replace(reg, '<br>');
            }
            , comma2br: function (data, option) {
                let value = myCommon.value(data, option.field), reg = new RegExp(',', 'g');
                return value.replace(reg, '<br>');
            }
            , dateTime: function (data, option) {
                let value = myCommon.table.fn(data, option);
                return value != null ? value.substr(option.short ? 2 : 0, option.short ? 14 : 16) : '';
            }
            , monthDay: function (data, option) {
                let value = myCommon.table.fn(data, option);
                return value != null ? value.substr(5, 5) : '';
            }
            , value: function (data, option) {
                return '<span>' + myCommon.table.fn(data, option) + '</span>';
            }
            , fn: function (data, option) {
                let value = myCommon.value(data, option.field);
                if ('function' == typeof option.fn) {
                    return option.fn(value, data, option);
                }
                return value;
            }
            , _execRowspan: function (fieldName, flag, index) {
                // 1为不冻结的情况，左侧列为冻结的情况
                let fixedNode = index == "1" ? $(".layui-table-body")[index - 1] : (index == "3" ? $(".layui-table-fixed-r") : $(".layui-table-fixed-l"));
                // 左侧导航栏不冻结的情况
                let child = $(fixedNode).find("td");
                let childFilterArr = [];
                // 获取data-field属性为fieldName的td
                for (let i = 0; i < child.length; i++) {
                    if (child[i].getAttribute("data-field") == fieldName) {
                        childFilterArr.push(child[i]);
                    }
                }
                // 获取td的个数和种类
                let childFilterTextObj = {};
                for (let i = 0; i < childFilterArr.length; i++) {
                    let childText = flag ? childFilterArr[i].innerHTML : childFilterArr[i].textContent;
                    if (childFilterTextObj[childText] == undefined) {
                        childFilterTextObj[childText] = 1;
                    } else {
                        let num = childFilterTextObj[childText];
                        childFilterTextObj[childText] = num * 1 + 1;
                    }
                }
                let canRowspan = true;
                let maxNum;//以前列单元格为基础获取的最大合并数
                let finalNextIndex;//获取其下第一个不合并单元格的index
                let finalNextKey;//获取其下第一个不合并单元格的值
                for (let i = 0; i < childFilterArr.length; i++) {
                    (!maxNum || maxNum > 9000) && (maxNum = $(childFilterArr[i]).prev().attr("rowspan") && fieldName != "8" ? $(childFilterArr[i]).prev().attr("rowspan") : 9999);
                    let key = flag ? childFilterArr[i].innerHTML : childFilterArr[i].textContent;//获取下一个单元格的值
                    let nextIndex = i + 1;
                    let tdNum = childFilterTextObj[key];
                    let curNum = maxNum < tdNum ? maxNum : tdNum;
                    if (canRowspan) {
                        for (let j = 1; j <= curNum && (i + j < childFilterArr.length);) {//循环获取最终合并数及finalNext的index和key
                            finalNextKey = flag ? childFilterArr[i + j].innerHTML : childFilterArr[i + j].textContent;
                            finalNextIndex = i + j;
                            if ((key != finalNextKey && curNum > 1) || maxNum == j) {
                                canRowspan = true;
                                curNum = j;
                                break;
                            }
                            j++;
                            if ((i + j) == childFilterArr.length) {
                                finalNextKey = undefined;
                                finalNextIndex = i + j;
                                break;
                            }
                        }
                        childFilterArr[i].setAttribute("rowspan", curNum);
                        if ($(childFilterArr[i]).find("div.rowspan").length > 0) {//设置td内的div.rowspan高度适应合并后的高度
                            $(childFilterArr[i]).find("div.rowspan").parent("div.layui-table-cell").addClass("rowspanParent");
                            $(childFilterArr[i]).find("div.layui-table-cell")[0].style.height = curNum * 38 - 10 + "px";
                        }
                        canRowspan = false;
                    } else {
                        childFilterArr[i].style.display = "none";
                    }
                    if (--childFilterTextObj[key] == 0 | --maxNum == 0 | --curNum == 0 | (finalNextKey != undefined && nextIndex == finalNextIndex)) {//||(finalNextKey!=undefined&&key!=finalNextKey)
                        canRowspan = true;
                    }
                }
            }
            /*
            * 竖向合并单元格
            * fieldName:合并单元格的列名，可以是数组
            * flag: true获取单元格html,false获取文本(默认)
            * index:1不冻结的(默认)2左侧冻结3右侧冻结
            * 示例
            * table.init('test', {
            *    done: function (res, curr, count) {
            *       myCommon.table.rowspan('province');
            *       myCommon.table.rowspan(['city', 'zone', 'username', 'joinTime', 'sign']);//支持数组
            *       myCommon.table.rowspan("8", true);
            *   }
            * });
            */
            , rowspan: function (fieldName, flag, index) {
                if (typeof fieldName == "string") fieldName = [fieldName];
                if (typeof index == "undefined") index = 1;
                for (let i = 0; i < fieldName.length; i++) {
                    myCommon.table._execRowspan(fieldName[i], flag, index);
                }
            }
        }
    };

    $(function () {
        //将数据值转换成名字
        $('[data-type-list][data-value]').each(function () {
            let $this = $(this)
                , value = $this.attr('data-value')
                , list = myCommon.getTypeList($this.attr('data-type-list'));
            $.each(list, function (i, n) {
                if (n.value == value) {
                    $this.text(n.name);
                    return false;
                }
            });
        });
        //将金额由分转成元
        $('[data-convert-money]').each(function () {
            $(this).text(myCommon.double2String(parseInt($(this).attr('data-convert-money'), 10) / myCommon.MONEY_UNIT));
        });
        //自动计算表格total处理
        $('.auto-compute-total [data-field]').each(function () {
            myCommon.tableSimpleTotal($(this).closest('table'), [$(this).attr('data-field')]);
        });
    });

    //暴露接口
    exports('myCommon', myCommon);
});